(function($){
    var defCfg = {
            thumbnail : true,  //是否生成缩略图.
            height : 80, //默认宽度自动.            
            uploadImmediately : true
        },
        _imgUploaderTmp = [
            '<div class="imgWrap hvBox">',
                '<img class="uploadedImg" src="' + ujs.getConfigRes('emptyImagePath') + '" />',                
            '</div>',
            '<div class="uploadCmdBar">',
                '<a class="imgUploadBtn delImg elipseButton h">Delete</a>',
                '<a class="imgUploadBtn addImg elipseButton">Add New ...</a>',
            '</div>',
            '<input class="hiddenFileField" type="file" value="" style="display:none;"/>'
        ].join('');
        
    //TODO: 可以修改此控件为，多图片上传控件.
	//single image uploader cmp constructor.
	//dependance1 : HeavyButton.
	function _SingleImgUploader(selector, cfg){		
		var _this = this;		
        //使支持事件注册.
        Observable.enable(this);		
	    this.$wrapper = $(selector);		    
		this.$wrapper.append(_imgUploaderTmp);
		
		_this.config = $.extend({}, defCfg, cfg);
		
		_this.$addImgBtn = _this.$wrapper.find('.addImg');
		_this.$delImgBtn = _this.$wrapper.find('.delImg');	
		
		_this.$imgWrap = _this.$wrapper.find('.imgWrap');
		_this.$uploadedImg = _this.$wrapper.find('.uploadedImg');
			
		_this.$hiddenFileField = _this.$wrapper.find('.hiddenFileField');
		
		_this.$hiddenFileField.on('click', function(){
		    _this.fire('beforeSelectImg');
		});
				
		_this.$wrapper.style(_this.config['style']);
				
		if(_this.config['width']){
		    _this.$imgWrap.css('width', _this.config['width']);		    
		}		
        _this.$imgWrap.css('height', _this.config['height']);    
        	
    	if(_this.config['toolbar'] === false){
    	    this.$wrapper.find('.uploadCmdBar').hide();
    	    this.$wrapper.find('.imgWrap').css('cursor', 'pointer').click(function(){
    	        _this.$hiddenFileField.click();
    	    });
    	}
        		    				
		this.$wrapper.delegate('.uploadCmdBar > .imgUploadBtn', 'click', function(e){
		    e.preventDefault();		    		
			if($(this).hasClass('delImg')){  //删除图片.
			    if(_this.$wrapper.attr('selectedvalue')){
    			    bubble.confirm('Are you sure deleting this photo?', function(){
    			        _this.$uploadedImg[0].src = ujs.getConfigRes('emptyImagePath');
    			        _this.$wrapper.attr('selectedvalue', '');    
    			        _this.$delImgBtn.addClass('h');   
    			    });
    			} else {
    			    bubble.msg('This photo has been deleted.');
    			}
			} else if($(this).hasClass('addImg') ){  //添加图片.
				_this.$hiddenFileField.click();
			}			
		});
		
		//选择并读取图片.
		_this.$hiddenFileField.bind('change',function(){
		    var fileField = this;		    
    		var file = fileField.files[0],
    		    fileType = file.type;
		    		    
		    _this.file = file;
		    _this.originalFile = file;
		    _this.fileType = fileType;
		    
    		if( file ){
    			var image = _this.$uploadedImg[0];
    			if(_this.config['thumbnail']){
        			ujs.browser.img.genThumbnail(
                        {
                            src : file,                        
                            width : _this.config['width'],
                            height : _this.config['height'],
                            isGetImgFileObj : true
                        }, 
                        function(thumbImgFile, thumbnailBase64, originalFileBase64Str){                                
                            _this.originalFileBase64Str = originalFileBase64Str;
                            _this.file = thumbImgFile;
                            image.src = thumbnailBase64;
                            //上传thumbnail.
                            if(_this.config['uploadImmediately']){
                                _this.upload();
                            }
                        }
                    );  
                }
    			image.src = ujs.browser.file.toLocalURL(file);
    			_this.fire('change', file);
    			
    			if(!_this.config['thumbnail'] && _this.config['uploadImmediately']){
        			_this.upload();
                }
			} else {
			    //若用户点击选择文件对话框中的cancel或close,则file为 undefined.
			}
		});
		//默认值.
		if(_this.config['value']){
		    _this.setValue(_this.config['value'], true);
		}	
	}
	
	_SingleImgUploader.prototype.upload = function(cb){
	    var _this = this;	    
	    if(!_this.getImgFile()){
	        cb && cb.call(this);
	        return this;
	    }	        
        ujs.ui.HeavyButton.regLoading( _this.$addImgBtn, {
            loadingText : 'uploading...'
        } );
        _this.$delImgBtn.attr('disabled', 'disabled');
        _this.fire('beforeUploading');    
        
        $.ajax({
            url: _this.getUploadApi(),
            data: this.getFormData(),
            cache: false,
            contentType: false,
            processData: false,         
            type: 'POST',
            success: ujs.hr(function(msg){
                if(Type.isString(msg['path'])){
                    _this.setValue(msg['path']);  
                }
                if(cb){
                    cb.call(_this, msg);
                }   
                _this.fire('upload', msg);       
            })
        }).done(function(){                            
            ujs.ui.HeavyButton.restore( _this.$addImgBtn );
            _this.$delImgBtn.removeAttr('disabled');
            _this.fire('afterUploading');  
            //清空fileField的值，以便于下次若选择同样的图片时，依然能够触发onChange事件. 
            _this.$hiddenFileField[0].value = '';
        });                        
	};
	
	_SingleImgUploader.prototype.getUploadApi = function(){
	    return this.config['api'];
	};
	
	_SingleImgUploader.prototype.setUploadApi = function(api){
        this.config['api'] = api;
        return this;
    };
	
	_SingleImgUploader.prototype.getImgFile = function(){
	    return this.file;
	};
	
	_SingleImgUploader.prototype.getOriginalFile = function(){
        return this.originalFile || this.file;
    };
    
    //------------------------同步获取图像文件缩略图文件对象及base64Str--------------------------
    
    _SingleImgUploader.prototype.getThumbnail = function(width, height){
        var _this = this;
        return ujs.browser.img.genThumbnail({
            async : false,
            src : _this.originalFileBase64Str,
            type : _this.fileType,
            width : width,
            height : height,
            isGetImgFileObj : true
        }); 
    };
    
    _SingleImgUploader.prototype.getThumbnailFile = function(){
        return this.getThumbnail.apply(this, Object.toArray(arguments))['file'];
    };
    
    _SingleImgUploader.prototype.getThumbnailBase64Str = function(){
        return this.getThumbnail.apply(this, Object.toArray(arguments))['base64'];
    };
    
    _SingleImgUploader.prototype.fillupImageFiles = function(formData, demension){        
        var imgFile = this.getImgFile();   
        if(imgFile){   
            //添加默认图片.
            var cfgWidth = this.config['width'],
                cfgHeight = this.config['height'];
            formData.append('icon_{0}_{1}'.format(cfgWidth, cfgHeight), imgFile);
            //添加指定的其它图片.
            if(demension && demension.length){
                for(var i=0; i<demension.length; i++){
                    var imgWidth = demension[i][0],
                        imgHeight = demension[i][1];
                    formData.append('icon_{0}_{1}'.format(imgWidth,imgHeight), this.getThumbnailFile(imgWidth,imgHeight));
                }
            }
        }
        return this;
    };
    
    //-----------------------------------------------------------------------------
    
	//get uploaded server image path.
	_SingleImgUploader.prototype.getValue = function(){
		return this.$wrapper.attr('selectedvalue') || this.getImgFile() || '';		
	};
		
	_SingleImgUploader.prototype.reset = function(){	    
	    this.$wrapper.removeAttr('selectedvalue');
        this.$uploadedImg[0].src = ujs.getConfigRes('emptyImagePath');
        this.$delImgBtn.addClass('h');
        this.file = null;
        this.originalFile = null;
	};
	
	//set image path.
    _SingleImgUploader.prototype.setValue = function(imgSrc, isSilent){
        if(imgSrc){
            this.$wrapper.attr('selectedvalue', imgSrc);
            this.$uploadedImg[0].src = imgSrc;
            this.$delImgBtn.removeClass('h');
            if(isSilent !== true){
                this.fire('change', imgSrc);
            }
        }  
    };
    
    //----------------------------------------------------------------------------------------------
    
    _SingleImgUploader.prototype.isEmpty = function(){
        return !this.getValue();        
    };
        
    _SingleImgUploader.prototype.markInvalid = function(){
        this.$wrapper.addClass('invalid');
    };
    
    //----------------------------------------------------------------------------------------------
	
	//get form images.
	_SingleImgUploader.prototype.getFormData = function(){
		var imgData = new FormData(),
            fileKey = this.config['fileKey'] || 'imgFile';
        
        if(!this.config['thumbnail']){
            imgData.append(fileKey, this.file);         
        } else {                               
            imgData.append(fileKey, base64.toFile(this.$uploadedImg.attr('src'), this.fileType));
        }  
            
        if(this.config['otherSize']){
            var otherSizeArr = this.config['otherSize'];
            for(var i=0; i<otherSizeArr.length; i++){
                imgData.append(
                    fileKey + '_{0}_{1}'.format(otherSizeArr[i]['width'], otherSizeArr[i]['height']), 
                    this.getThumbnail(otherSizeArr[i]['width'], otherSizeArr[i]['height'])['file']
                );
            }  
        }
        
		return imgData;		
	};
	
	//----------------------------------------------------------------------------------------------
	
	//init interface.
	$.fn.singleImgUploader = function(cfg){		
		this.each(function(){
		    var imgUploaderObj = new _SingleImgUploader(this, cfg);
		    Observable.regEvent(imgUploaderObj, cfg);			    
		    $(this).data('singleImgUploader', imgUploaderObj).data('formField', imgUploaderObj);
		});
		return this;
	};
})($);